#include "Game.h"
#include "../Muzzy A Wrappers/D3DManager.h"
#include "../Muzzy A Wrappers/TextureManager.h"
#include "../Muzzy A Wrappers/DirectInput.h"
#include "../Muzzy A Wrappers/SoundManager.h"
#include "../Muzzy A Wrappers/Timer.h"
#include "GamePlayState.h"
#include "MainMenuState.h"
#include "IGameState.h"
#include "GameCursor.h"


Game::Game(void)
{
	d3dManager		= nullptr;
	textureManager	= nullptr;
	soundManager	= nullptr;
	shaderManager	= nullptr;
	input			= nullptr;
	time			= nullptr;
	cursor			= nullptr;
}


Game::~Game(void)
{
}

void Game::Render()
{
	if(!running) return;

	d3dManager->Present();
	d3dManager->Clear(Color(0,0,0,1));
	d3dManager->Begin();

	// Draw 3D Items here
	states.back()->Render();

	d3dManager->End();
}

void Game::Update()
{
	if(!running) return;

	// We need to update the input buffers
	input->Update();

	// Update the position of the cursor
	cursor->Update();

	// Update the game
	states.back()->Update();
}

void Game::Input()
{
	// Easy exit
	if(input->KeyPressed(keyEscape))
	{
		RemoveState(true);
		return;
	}

	states.back()->Input();
}

Game* Game::getInstance()
{
	static Game game;
	return &game;
}

void Game::Initialize()
{
	// Get access to all the managers
	d3dManager		= D3DManager::getInstance();
	textureManager	= TextureManager::getInstance();
	soundManager	= SoundManager::getInstance();
	input			= DirectInput::getInstance();
	time			= Timer::getInstance();
	cursor			= GameCursor::getInstance();

	// Reset the timer so it's ready to use
	time->Reset();

	// The game is about to start running
	running = true;

	// Set the starting game state
	AddState(GamePlayState::getInstance());

	// Load the image for the cursor
	//cursor->setTextureID(textureManager->LoadTexture("Assets/Textures/diamond.png"));

	// Turn on alpha blending for transparency
	d3dManager->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
	d3dManager->getDevice()->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCCOLOR);
	d3dManager->getDevice()->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
}

void Game::Shutdown()
{
	//////////////////////////////////////////////////////////////////////////
	// Make sure all game states are cleaned up
	while(!states.empty())
	{
		states.back()->Exit();
		states.pop_back();
	}

	//////////////////////////////////////////////////////////////////////////
	// Safety!
	d3dManager		= nullptr;
	textureManager	= nullptr;
	soundManager	= nullptr;
	shaderManager	= nullptr;
	input			= nullptr;
	cursor			= nullptr;
}

void Game::Run()
{
	// The Game Loop
	while(d3dManager->Running() && running)
	{
		// Update the game time
		time->Update();

		// Each frame
		Input();
		Render();
		Update();
	}

	// Clean up all memory
	for(unsigned i = 0; i < states.size();++i)
		states[i]->Exit();
}

void Game::AddState( IGameState *pState )
{
	if(pState)
	{
		pState->Enter();
		states.push_back(pState);
	}
	else
	{
		for(unsigned i = 0;i < states.size();++i)
			states[i]->Exit();

		running = false;
	}
}

void Game::RemoveState(bool bEndGame)
{
	states.front()->Exit();

	std::vector<IGameState*>::iterator iter;
	iter = states.begin();

	states.erase(iter);

	running = !bEndGame;
}
